package com.hibuy.pc.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @param <T>
 */
public class ExportExcel<T> {

    /**
     * 导出
     * @param title 表格标题名
     * @param headers 表格属性列名数组
     * @param dataset
     * @param out 与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
     * @param pattern 如果有时间数据，设定输出格式。默认为"yyy-MM-dd"
     */
    public void exportExcel (String title, String[] headers,
                             Collection<T> dataset, OutputStream out, String pattern){

        //声明一个工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        //声明一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        //设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth(15);
        //生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        //设置样式
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

        //生成一个字体
        HSSFFont font = workbook.createFont();
        font.setColor(HSSFColor.VIOLET.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //将字体样式应用到当前样式
        style.setFont(font);

        //生成并设置另一个样式
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
        style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        //生成另一个字体
        HSSFFont font2 = workbook.createFont();
        font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        //把字体应用到当前的样式
        style2.setFont(font2);

        //声明一个画图的顶级管理器
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
        //定义注释的大小和位置
        HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));
        //设置注释内容
        comment.setString(new HSSFRichTextString("注释内容"));
        //设置注释作者，当鼠标移动到单元格上是可以在状态栏看到该内容
        comment.setAuthor("dyg");

        //产生表格标题
        HSSFRow row = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }

        //遍历集合数据，产生数据行
        Iterator<T> iterator = dataset.iterator();
        int index = 0;
        while (iterator.hasNext()){
            index++;
            row = sheet.createRow(index);
            T t = iterator.next();
            //利用反射，根据javabean属性的先后顺序，动态调用getXX()方法得到属性值
            Field[] fields = t.getClass().getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(style2);
                Field field = fields[i];
                String fieldName = field.getName();
                String getMethodName = "get"
                        + fieldName.substring(0,1).toUpperCase()
                        + fieldName.substring(1);

                try {
                    Class tCls = t.getClass();
                    Method method = tCls.getMethod(getMethodName, new Class[]{});
                    Object value = method.invoke(t, new Object[]{});

                    //判断值得类型后进行强制类型转换
                    String textValue = null;
                    if(value instanceof Boolean){

                    }else if (value instanceof Date) {
                        Date date = (Date) value;
                        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                        textValue = sdf.format(date);
                    }else if (value instanceof byte[]) {
                        //设置行高
                        row.setHeightInPoints(60);
                        //设置如偏所在列宽度
                        sheet.setColumnWidth(i, (short) (35.7 * 80));
                        byte[] byteValue = (byte[]) value;
                        HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short)6,index,(short) 6,index);
                        anchor.setAnchorType(2);
                        patriarch.createPicture(anchor,workbook.addPicture(byteValue,HSSFWorkbook.PICTURE_TYPE_JPEG));
                    }else {
                        textValue = value.toString();
                    }

                    // 如果不是图片数据，就利用正则表达式判断textValue是否全部由数字组成
                    if(textValue != null){
                        Pattern compile = Pattern.compile("^//d+(//.//d+)?$");
                        Matcher matcher = compile.matcher(textValue);
                        if(matcher.matches()){
                            //数字当做double处理
                            cell.setCellValue(Double.parseDouble(textValue));
                        }else {
                            HSSFRichTextString richString = new HSSFRichTextString(textValue);
                            HSSFFont font3 = workbook.createFont();
                            font3.setColor(HSSFColor.BLUE.index);
                            richString.applyFont(font3);
                            cell.setCellValue(richString);
                        }
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            }
        }

        try {
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }





    public static void main(String[] args) {
        try {
        ExportExcel<ExamSite> exportExcel = new ExportExcel<>();
        String title = "管理人员列表";
        String[] header = {"考点标识","考点名称","考点代码"," 管理员密码"};
        ExamSite examSite = new ExamSite();
        examSite.setExamSiteID(590);
        examSite.setExamSiteName("栖霞开放大学");
        examSite.setExamSiteCode("YYNJ2017");
        examSite.setSitePwd("XDTis87WHjg=");

        List<ExamSite> list = new ArrayList<>();
        list.add(examSite);

        OutputStream out = new FileOutputStream("D://ExamSite.xls");
        String pattern = "yyyy-MM-dd HH:mm:ss";
        exportExcel.exportExcel(title,header,list,out,pattern);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class ExamSite {

    /**
     * 考点标识
     */
    private Integer examSiteID;
    /**
     * 考点名称
     */
    private String examSiteName;
    /**
     * 考点代码
     */
    private String examSiteCode;
    /**
     * 管理员密码
     */
    private String sitePwd;

    public Integer getExamSiteID() {
        return examSiteID;
    }

    public void setExamSiteID(Integer examSiteID) {
        this.examSiteID = examSiteID;
    }

    public String getExamSiteName() {
        return examSiteName;
    }

    public void setExamSiteName(String examSiteName) {
        this.examSiteName = examSiteName;
    }

    public String getExamSiteCode() {
        return examSiteCode;
    }

    public void setExamSiteCode(String examSiteCode) {
        this.examSiteCode = examSiteCode;
    }

    public String getSitePwd() {
        return sitePwd;
    }

    public void setSitePwd(String sitePwd) {
        this.sitePwd = sitePwd;
    }
}
